import { InfoRender } from "./InfoRender";
import { SkerWorker } from "./SkerWorker";
import { ToolsRender } from "./ToolsRender";
import { Updater } from "./Updater";
import { clearAdv } from "./adv";
import { createRootAst, uploadXml } from "./ast";
import { clearCache } from "./clearCache";
import { closeApp } from "./closeApp";
import { formatMinute, getDeviceUuid } from "./utils";

export abstract class SkerMaster {
    tools: ToolsRender;
    info: InfoRender;
    updater: Updater;
    isExit: boolean = false;
    autoRun: boolean = false;
    worker: SkerWorker;
    // 当前状态
    _status: string = `ready`

    endTime: string;
    startTime: string;
    currentPkg: string;
    sleepStartTime: number = new Date().getTime();

    get status() {
        return this._status;
    }
    set status(status: string) {
        this._status = status;
        this.update()
    }
    
    key: string;
    getKey: () => string;
    constructor(updater: Updater, getKey: () => string) {
        setInterval(this.check.bind(this), 1000)
        this.updater = updater;
        events.on('exit', this.onExit.bind(this))
        this.getKey = getKey;
        this.key = this.getKey();
    }
    generateDate(time: string): Date {
        if (!time) {
            this.msg = `时间格式有误，请检查配置阐述`
            sleep(1000)
            return new Date();
        }
        const [h, m, s] = time.split(':')
        const n = new Date();
        n.setHours(parseInt(h))
        n.setMinutes(parseInt(m))
        n.setSeconds(parseInt(s))
        return n;
    }
    private isSleepTime() {
        const now = new Date();
        const startTime = this.generateDate(this.startTime)
        const endTime = this.generateDate(this.endTime)
        // 当前时间大于结束
        if (now > startTime && now < endTime) {
            return false;
        }
        return true;
    }
    abstract toJson(): object;
    saveStorage() {
        const json = this.toJson()
        this.worker.tryPost('client/update', {
            uuid: getDeviceUuid(),
            data: json
        }, {})
    }
    launchPackage() {
        let success = false;
        while (!success && !this.isExit) {
            const root = createRootAst()
            success = root?.packageName == this.currentPkg
            if (!success) {
                this.msg = `正在打开${this.currentPkg}`
                launchPackage(this.currentPkg)
                selector().text('允许').findOne(1000 * 10)?.click()
            }
        }
        sleep(1000)
        return success;
    }
    check() {
        this.update();
        if (this.autoRun) {
            if (this.isSleepTime()) {
                if (!this.status.startsWith('stop')) {
                    this.status = `stoping`
                    threads.start(() => {
                        this.worker.stop()
                        this.saveStorage();
                        if (this.launchPackage()) {
                            clearCache(this.currentPkg)
                        } else {
                            closeApp(this.currentPkg)
                        }
                        this.sleepStartTime = new Date().getTime()
                        this.status = `stop.sleep`
                    })
                    return;
                }
                this.update(`休息中${formatMinute((new Date().getTime() - this.sleepStartTime) / 1000)}`);
            } else {
                if (!this.status.startsWith('start')) {
                    this.status = `starting`;
                    threads.start(() => {
                        this.worker.onInit();
                        this.worker.start();
                    })
                    return;
                }
            }
        }
    }
    onExit() {
        this.isExit = true;
        this.worker.isRuning = false;
        this.status = 'stop'
    }
    startClearAdv() {
        threads.start(() => {
            while (!this.isExit) {
                try {
                    device.wakeUpIfNeeded();
                    clearAdv([])
                } catch (e) {
                    console.error(e)
                } finally {
                    sleep(1000)
                }
            }
        });
    }
    render(): void {
        this.tools.render()
        this.info.render();
    }
    onStartSuccess(): void {
        this.status = `start`
        this.tools.start()
    }
    onStopSuccess(): void {
        this.status = `stop`
        this.tools.stop()
        toastLog(`应用已停止`)
    }
    onReady(): void {
        this.status = `ready`
    }
    onInfo() {
        if (this.info.isShow()) {
            this.info?.close();
        } else {
            this.info?.open();
        }
    }
    onStart() {
        this.autoRun = false;
        if (!this.status.startsWith('start')) {
            this.status = `starting`
            this.worker.start()
            this.autoRun = true;
            return;
        }
        if (!this.status.startsWith('stop')) {
            this.status = `stoping`
            this.worker.stop()
            return;
        }
    }
    onKill() {
        exit()
    }
    onBug() {
        this.update(`问题正在上传`)
        uploadXml(`debug`, `debug`)
        sleep(1000)
        this.update(`问题上传成功`)
    }
    onUpdate() {
        this.worker.stop()
        this.updater.update();
        events.broadcast.emit(`RESTART`, engines.myEngine().getSource())
    }
    onClear() {
        this.worker.clear()
    }
    onClick(e: string) {
        threads.start(() => {
            switch (e) {
                case 'info':
                    return this.onInfo();
                case 'start':
                    return this.onStart();
                case 'kill':
                    return this.onKill()
                case 'bug':
                    return this.onBug()
                case 'update':
                    return this.onUpdate();
                case 'clear':
                    return this.onClear()
            }
        })
    }
    init() {
        if (!floaty.checkPermission()) {
            floaty.requestPermission()
            exit();
        }
        auto.waitFor();
        this.tools = new ToolsRender(this.onClick.bind(this));
        this.info = new InfoRender();
        this.startClearAdv();
        this.render();
        threads.start(() => {
            const runingTime = new Date().getTime() + 1000 * 10
            let dec = 1000 * 10;
            while (dec > 0) {
                dec = runingTime - new Date().getTime()
                this.update(`${formatMinute(dec / 1000)}后启动脚本`)
                sleep(1000)
            }
            this.autoRun = true;
        })

    }
    abstract print(msg: string): string;
    // 打印消息到控制台
    private msg: string;
    update(str?: string): void {
        if (!this) return;
        if (str) this.msg = str;
        const msg = this.print(str || this.msg);
        this.info.update(msg)
    }
}
